package com.hyh.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyh.product.Mapper.ProductMapper;
import com.hyh.product.domain.Product;
import com.hyh.product.result.MybatisResult;
import com.hyh.product.result.PageResult;
import com.hyh.product.service.ProductService;
import com.hyh.product.util.RedisCodeUtil;
import io.netty.util.internal.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper;

    @Value("${file.upload-dir}")
    private String uploadDir;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    // 删除某个商品
    @Override
    public PageResult deleteProduct(Long id) {
        int i = productMapper.deleteById(id);
        if (i == 0)
            return new PageResult(HttpStatus.HTTP_CREATED, null, "删除失败");
        return new PageResult(HttpStatus.HTTP_OK, null, "删除成功");
    }

    // 更新某个商品
    @Override
    public PageResult updateProduct(Long id) {
        Product product = productMapper.selectById(id);

        return null;
    }

    // 更新库存
    @Override
    public PageResult updateStock(Long id, Integer stock) {
        Product product = productMapper.selectById(id);
        if (product.getStockQuantity() < stock)
            return new PageResult(HttpStatus.HTTP_CREATED, null, "库存不足");
        int stk = product.getStockQuantity() - stock;
        product.setStockQuantity(stk);
        int i = productMapper.updateById(product);
        if (i == 0)
            return new PageResult(HttpStatus.HTTP_CREATED, null, "更新失败");
        return new PageResult(HttpStatus.HTTP_OK, null, "更新成功");
    }

    // 根据商品id查询商品信息 将信息缓存到redis当中
    @Override
    public Product getProductById(Long id) {
        //查询redis当中的数据
        // String product = stringRedisTemplate.opsForValue().get(RedisCodeUtil.PRODUCT_KEY + id);
        Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(RedisCodeUtil.PRODUCT_KEY + id);
        if(!entries.isEmpty()){
            // 将map转为bean => product
            return BeanUtil.fillBeanWithMap(entries, new Product(),false);
        }

        // 判断是否为空
        // if((StrUtil.isNotBlank(product))){
        //     return JSONUtil.toBean(product, Product.class);
        //
        // }
        // 不存在的话 查询数据库
        Product product2 = productMapper.selectById(id);
        if (product2 == null)
            return null;
        String replaceTitle = product2.getTitle().replaceAll("<font[^>]*>", "").replaceAll("</font>", "");
        product2.setTitle(replaceTitle);
        // 将数据存入redis
        // stringRedisTemplate.opsForValue().set(RedisCodeUtil.PRODUCT_KEY + id,
        //         JSONUtil.toJsonStr(product2),
        //         RedisCodeUtil.PRODUCT_KEY_TTL, TimeUnit.MINUTES);

        Map<String, Object> stringObjectMap = BeanUtil.beanToMap(product2, new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(true).setFieldValueEditor((fieldName, fieldValue) -> {
                    if (fieldValue == null)
                        return null;
                    return fieldValue.toString();
                }));

        stringRedisTemplate.opsForHash().putAll(RedisCodeUtil.PRODUCT_KEY + id,
                stringObjectMap);
        stringRedisTemplate.expire(RedisCodeUtil.PRODUCT_KEY + id,
                RedisCodeUtil.PRODUCT_KEY_TTL, TimeUnit.MINUTES);
        // 返回数据
        return product2;
    }


    // 发布商品
    @Override
    public PageResult publishProduct(Product product, MultipartFile[] files) {
        List<String> fileNames = new ArrayList<>();
        // 获取formData中的字段
        for (MultipartFile file : files) {
            try {
                // 获取文件名
                String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));

                // 拼接文件保存路径
                String filePath = uploadDir + '/' + fileName;
                product.setImgSrc(filePath);
                // 保存文件
                file.transferTo(new File(filePath));
                fileNames.add(fileName);
            } catch (IOException e) {
                throw new RuntimeException("Failed to store file " + file.getOriginalFilename(), e);
            }
        }
        // 插入数据到数据库
        productMapper.insert(product);
        return new PageResult(HttpStatus.HTTP_OK, product, "发布成功");
    }

    // 发布图片资源
    @Override
    public PageResult publishImage(MultipartFile[] files) {
        List<String> fileNames = new ArrayList<>();
        for (MultipartFile file : files) {
            try {
                // 获取文件名
                String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));

                // 拼接文件保存路径
                String filePath = uploadDir + File.separator + fileName;

                // 保存文件
                file.transferTo(new File(filePath));
                fileNames.add(fileName);
            } catch (IOException e) {
                throw new RuntimeException("Failed to store file " + file.getOriginalFilename(), e);
            }
        }

        return new PageResult(HttpStatus.HTTP_OK, fileNames, "上传成功");
    }

    @Override
    public PageResult getAllProduct() {
        // 1 查询redis中的数据
        List<String> list = stringRedisTemplate.opsForList().range(RedisCodeUtil.PRODUCT_KEY_ALL, 0, -1);
        // 2数据存在 返回
        if(Objects.nonNull(list) && !list.isEmpty()){
            List<Product> productList = new ArrayList<>();
            list.forEach(product -> {
                productList.add(JSONUtil.toBean(product, Product.class));
            });
            return new PageResult(HttpStatus.HTTP_OK, productList, "查询成功");
        }
        // 3数据不存在 查询数据库
        List<Product> products = productMapper.selectList(null);
        products.forEach(product -> {
            String replaceTitle = product.getTitle().replaceAll("<font[^>]*>", "").replaceAll("</font>", "");
            product.setTitle(replaceTitle);
            String jsonStr = JSONUtil.toJsonStr(product);
            // 4将数据存入redis
            stringRedisTemplate.opsForList().rightPush(RedisCodeUtil.PRODUCT_KEY_ALL,
                    jsonStr);
        });
        //返回数据
        return new PageResult(HttpStatus.HTTP_OK, products, "查询成功");
    }


    // 分页查询商品
    @Override
    public PageResult getProductByPage(Integer page, Integer size) {
        // 1 查询redis中的数据
        List<String> list = stringRedisTemplate.opsForList().range(RedisCodeUtil.PRODUCT_PRODUCT_PAGE + page, 0, -1);
        // 2数据存在 返回
        if(Objects.nonNull(list) && !list.isEmpty()){
            List<Product> productList = new ArrayList<>();
            list.forEach(product -> {
                productList.add(JSONUtil.toBean(product, Product.class));
            });
            return new PageResult(HttpStatus.HTTP_OK, productList, "查询成功");
        }
        // 3数据不存在 查询数据库
        QueryWrapper<Product> qw = new QueryWrapper<>();
        IPage<Product> page1 = new Page<>(page, size);
        productMapper.selectPage(page1, qw);
        MybatisResult<Product> products = new MybatisResult<>();
        products.setTotal((int) page1.getTotal());
        products.setList(page1.getRecords());
        products.getList().forEach(product -> {
            String replaceTitle = product.getTitle().replaceAll("<font[^>]*>", "").replaceAll("</font>", "");
            product.setTitle(replaceTitle);
            String jsonStr = JSONUtil.toJsonStr(product);
            // 4将数据存入redis
            stringRedisTemplate.opsForList().rightPush(RedisCodeUtil.PRODUCT_PRODUCT_PAGE + page,
                    jsonStr);
        });
        //返回数据
        return new PageResult(HttpStatus.HTTP_OK, products, "查询成功");
    }
}
